home *** CD-ROM | disk | FTP | other *** search
/ Software Vault: The Gold Collection / Software Vault - The Gold Collection (American Databankers) (1993).ISO / cdr53 / 251_01.zip / ADVCOM.C < prev    next >
Text File  |  1993-04-01  |  15KB  |  657 lines

  1. /* advcom.c - a compiler for adventure games */
  2. /*
  3.     Copyright (c) 1986, by David Michael Betz
  4.     All rights reserved
  5. */
  6.  
  7. #include "advcom.h"
  8. #include "advavl.h"
  9. #include "advdbs.h"
  10.  
  11. /* symbol tables */
  12. SYMBOL *symbols;
  13. ARGUMENT *arguments;
  14. ARGUMENT *temporaries;
  15.  
  16. /* adventure id information */
  17. char aname[19];
  18. int aversion;
  19.  
  20. /* word table */
  21. int wtable[WMAX+1],wcnt;
  22.  
  23. /* object table */
  24. int otable[OMAX+1],ocnt;
  25.  
  26. /* action table */
  27. int atable[AMAX+1],acnt;
  28.  
  29. /* constant, variable and property symbol counts */
  30. int ccnt,vcnt,pcnt;
  31.  
  32. /* data and code space */
  33. char *data,*code;
  34. int dptr,cptr;
  35.  
  36. /* buffer for building an object */
  37. int objbuf[OSIZE];
  38. int nprops;
  39.  
  40. /* global variables */
  41. char ifile[FMAX];    /* input file name */
  42. char ofile[FMAX];    /* output file name */
  43. FILE *ifp;        /* input file pointer */
  44. unsigned int msgoff;    /* message section offset */
  45. TREE *words;        /* word tree */
  46. int curwrd;        /* current word number */
  47. int curobj;        /* current object */
  48. int curact;        /* current action */
  49. int def_flag;        /* default action flag value */
  50. int def_mask;        /* default action mask value */
  51.  
  52. /* header information variables */
  53. int h_init;        /* initialization code */
  54. int h_update;        /* update code */
  55. int h_before;        /* before handler code */
  56. int h_after;        /* after handler code */
  57. int h_error;        /* error handling code */
  58.  
  59. /* external routines */
  60. extern char *malloc();
  61. extern char *calloc();
  62. extern TREE *tnew();
  63.  
  64. /* external variables */
  65. extern int errcount;    /* error count */
  66. extern int t_value;    /* token value */
  67. extern char t_token[];    /* token string */
  68. extern char *t_names[];    /* token names */
  69. extern long ad_foff;    /* data file offset */
  70.  
  71. /* forward declarations */
  72. SYMBOL *sfind();
  73. SYMBOL *senter();
  74. char *save();
  75.  
  76. /* main - the main routine */
  77. main(argc,argv)
  78.   int argc; char *argv[];
  79. {
  80.     int tkn,obj,i;
  81.  
  82.     /* initialize */
  83. #ifdef MAC
  84.     macinit(ifile,ofile);
  85. #else
  86.     printf("ADVCOM v1.2 - Copyright (c) 1986, by David Betz\n");
  87. #endif
  88.     wcnt = ocnt = acnt = ccnt = vcnt = pcnt = msgoff = 0;
  89.     symbols = NULL; arguments = temporaries = NULL;
  90.     h_init = h_update = h_before = h_after = h_error = NIL;
  91.     def_flag = def_mask = 0;
  92.     aname[0] = 0;
  93.     sinit();
  94.  
  95.     /* setup the code and data space */
  96.     if ((data = calloc(1,DMAX)) == 0)
  97.     fail("insufficient memory");
  98.     if ((code = calloc(1,CMAX)) == 0)
  99.     fail("insufficient memory");
  100.     dptr = cptr = 1;    /* make sure nothing has a zero offset */
  101.  
  102.     /* get the file name */
  103. #ifndef MAC
  104.     if (argc < 2)
  105.     fail("usage: advcom <file> [ <ofile> ]");
  106.     strcpy(ifile,argv[1]); strcat(ifile,".adv");
  107.     strcpy(ofile,(argc < 3 ? argv[1] : argv[2])); strcat(ofile,".dat");
  108. #endif
  109.  
  110.     /* open the input file */
  111.     if ((ifp = fopen(ifile,"r")) == NULL)
  112.     fail("can't open input file");
  113.  
  114.     /* create and initialize the output file */
  115.     ad_create(ofile);
  116.     for (i = 0; i++ < 512; ad_putc('\0'))
  117.     ;
  118.  
  119.     /* create the word tree */
  120.     words = tnew();
  121.  
  122.     /* enter builtin constants */
  123.     center("t",-1);
  124.     center("nil",0);
  125.  
  126.     /* enter the builtin variables */
  127.     venter("$actor");
  128.     venter("$action");
  129.     venter("$dobject");
  130.     venter("$ndobjects");
  131.     venter("$iobject");
  132.     venter("$ocount");
  133.  
  134.     /* enter the preposition "to" */
  135.     add_word("to",WT_PREPOSITION);
  136.  
  137.     /* process statements until end of file */
  138.     while ((tkn = token()) == T_OPEN) {
  139.     frequire(T_IDENTIFIER);
  140.  
  141.     /* identification statement */
  142.     if (match("adventure"))
  143.         do_adventure();
  144.  
  145.     /* vocabulary statements */
  146.     else if (match("adjective"))
  147.         do_word(WT_ADJECTIVE);
  148.     else if (match("preposition"))
  149.         do_word(WT_PREPOSITION);
  150.     else if (match("conjunction"))
  151.         do_word(WT_CONJUNCTION);
  152.     else if (match("article"))
  153.         do_word(WT_ARTICLE);
  154.     else if (match("synonym"))
  155.         do_synonym();
  156.  
  157.     /* constant, variable, function and default definition statements */
  158.     else if (match("define"))
  159.         do_define();
  160.     else if (match("variable"))
  161.         do_variable();
  162.     else if (match("default"))
  163.         do_default();
  164.  
  165.     /* property definition statement */
  166.     else if (match("property"))
  167.         do_defproperty();
  168.  
  169.     /* handle the init, before and after code statements */
  170.     else if (match("init"))
  171.         h_init = do_code(t_token);
  172.     else if (match("update"))
  173.         h_update = do_code(t_token);
  174.     else if (match("before"))
  175.         h_before = do_code(t_token);
  176.     else if (match("after"))
  177.         h_after = do_code(t_token);
  178.     else if (match("error"))
  179.         h_error = do_code(t_token);
  180.  
  181.     /* action definition statement */
  182.     else if (match("action"))
  183.         do_action();
  184.  
  185.     /* object definition statements */
  186.         else if (match("object"))
  187.         do_object(t_token,NIL);
  188.  
  189.     /* object instance definition statements */
  190.     else if (obj = ofind(t_token))
  191.         do_object(t_token,obj);
  192.  
  193.     /* error, unknown statement */
  194.     else
  195.         error("Unknown statement type");
  196.     }
  197.     require(tkn,T_EOF);
  198.  
  199.     /* close the input file */
  200.     fclose(ifp);
  201.  
  202.     /* output the data structures */
  203.     output();
  204.  
  205.     /* close the output file */
  206.     ad_close();
  207. }
  208.  
  209. /* getvalue - get a value */
  210. int getvalue()
  211. {
  212.     SYMBOL *sym;
  213.  
  214.     switch (token()) {
  215.     case T_IDENTIFIER:    if (sym = sfind(t_token))
  216.                 return (sym->s_value);
  217.             return (oenter(t_token));
  218.     case T_NUMBER:    return (t_value);
  219.     case T_STRING:    return (t_value);
  220.     default:        error("Expecting identifier, number or string");
  221.             return (0);
  222.     }
  223. }
  224.  
  225. /* dalloc - allocate data space */
  226. int dalloc(size)
  227.   int size;
  228. {
  229.     if ((dptr += size) > DMAX)
  230.     fail("out of data space");
  231.     return (dptr - size);
  232. }
  233.  
  234. /* add_word - add a word to the dictionary */
  235. int add_word(str,type)
  236.   char *str; int type;
  237. {
  238.     if ((curwrd = tfind(words,str)) == NIL) {
  239.     if (wcnt < WMAX) {
  240.         curwrd = ++wcnt;
  241.         wtable[curwrd] = type;
  242.         tenter(words,str);
  243.     }
  244.     else {
  245.         error("too many words");
  246.         curwrd = 0;
  247.     }
  248.     }
  249.     else if (wtable[curwrd] == WT_UNKNOWN)
  250.     wtable[curwrd] = type;
  251.     else if (type != WT_UNKNOWN && type != wtable[curwrd])
  252.     error("Ambiguous word type");
  253.     return (curwrd);
  254. }
  255.  
  256. /* add_synonym - add a synonym to a word */
  257. int add_synonym(str,wrd)
  258.   char *str; int wrd;
  259. {
  260.     curwrd = wrd;
  261.     return (tenter(words,str));
  262. }
  263.  
  264. /* getword - get a word from an object field */
  265. int getword(off)
  266.   int off;
  267. {
  268.     return ((data[off] & 0xFF) | (data[off+1] << 8));
  269. }
  270.  
  271. /* putword - put a word into an object field */
  272. putword(off,dat)
  273.   int off,dat;
  274. {
  275.     data[off] = dat;
  276.     data[off+1] = dat >> 8;
  277. }
  278.  
  279. /* getbyte - get a byte from an object field */
  280. int getbyte(off)
  281.   int off;
  282. {
  283.     return (data[off]);
  284. }
  285.  
  286. /* putbyte - put a byte into an object field */
  287. putbyte(off,dat)
  288.   int off,dat;
  289. {
  290.     data[off] = dat;
  291. }
  292.  
  293. /* output - output the binary data structures */
  294. output()
  295. {
  296.     int woff,wsize;    /* word table offset and size */
  297.     int ooff,osize;    /* object table offset and size */
  298.     int aoff,asize;    /* action table offset and size */
  299.     int toff,tsize;    /* word type table offset and size */
  300.     int voff,vsize;    /* variable table offset and size */
  301.     int soff,ssize;    /* save area offset and size */
  302.     int dsize;        /* data size without dictionary */
  303.     int dbase,cbase,size,mblk,dblk,i;
  304.  
  305.     /* make sure the adventure id information is present */
  306.     if (aname[0] == 0) {
  307.     xerror("no adventure identification information");
  308.     strcpy(aname,"ADVENTURE");
  309.     aversion = 0;
  310.     }
  311.  
  312.     /* pad the remainder of this message block */
  313.     while (msgoff & 0x007F)
  314.     { ad_putc('\0'); ad_putc('\0'); ad_putc('\0'); ad_putc('\0'); msgoff++; }
  315.  
  316.     /* save the size of the data area before the dictionary */
  317.     dsize = dptr;
  318.  
  319.     /* insert the vocabulary into the data array */
  320.     woutput(words->tr_root);
  321.  
  322.     /* compute table offsets */
  323.     woff = 0;            wsize = tentries(words) * 2 + 2;
  324.     toff = woff + wsize; tsize = wcnt;
  325.     ooff = toff + tsize; osize = ocnt * 2 + 2;
  326.     aoff = ooff + osize; asize = acnt * 2 + 2;
  327.     voff = aoff + asize; vsize = vcnt * 2 + 2;
  328.     dbase = voff + vsize;
  329.     cbase = dbase + dptr;
  330.  
  331.     /* compute the resident structure size */
  332.     size = wsize+tsize+osize+asize+vsize+dptr+cptr;
  333.  
  334.     /* set the save area parameters */
  335.     soff = voff; ssize = vsize + dsize;
  336.  
  337.     /* compute the first block for message text */
  338.     mblk = 1;
  339.     dblk = (int)(ad_foff >> 9);
  340.  
  341.     /* output the word table */
  342.     word_out(tentries(words));
  343.     wtoutput(words->tr_root);
  344.  
  345.     /* output the word type table */
  346.     for (i = 1; i <= wcnt; i++)
  347.     byte_out(wtable[i]);
  348.  
  349.     /* output the object table */
  350.     word_out(ocnt);
  351.     for (i = 1; i <= ocnt; i++) {
  352.     if (otable[i] == NIL)
  353.         undef_object(i);
  354.     word_out(otable[i]);
  355.     }
  356.  
  357.     /* output the action table */
  358.     word_out(acnt);
  359.     for (i = 1; i <= acnt; i++)
  360.     word_out(atable[i]);
  361.  
  362.     /* beginning of saveable data */
  363.  
  364.     /* output the variable table */
  365.     word_out(vcnt);
  366.     for (i = 1; i <= vcnt; i++)
  367.     word_out(NIL);
  368.  
  369.     /* output the data space */
  370.     for (i = 0; i < dptr; )
  371.     byte_out(data[i++]);
  372.  
  373.     /* end of saveable data */
  374.  
  375.     /* output the code space */
  376.     for (i = 0; i < cptr; )
  377.     byte_out(code[i++]);
  378.  
  379.     /* output the file header */
  380.     ad_seek(0L);
  381.     word_out(size);    /* resident structure size */
  382.     str_out("ADVSYS",6);/* magic information */
  383.     word_out(VERSION);    /* data structure version number */
  384.     str_out(aname,18);    /* adventure name */
  385.     word_out(aversion);    /* adventure version number */
  386.     word_out(woff);    /* word table offset */
  387.     word_out(toff);    /* word type table offset */
  388.     word_out(ooff);    /* object table offset */
  389.     word_out(aoff);    /* action table offset */
  390.     word_out(voff);    /* variable table offset */
  391.     word_out(dbase);    /* base of data */
  392.     word_out(cbase);    /* base of code */
  393.     word_out(dblk);    /* first data block */
  394.     word_out(mblk);    /* first message text block */
  395.     word_out(h_init);    /* initialization code */
  396.     word_out(h_update);    /* update code */
  397.     word_out(h_before);    /* before handler code */
  398.     word_out(h_after);    /* after handler code */
  399.     word_out(h_error);    /* error handling code */
  400.     word_out(soff);    /* save area offset */
  401.     word_out(ssize);    /* save area size */
  402.  
  403.     /* show statistics */
  404.     printf("[ words:      %d ]\n",tentries(words));
  405.     printf("[ word types: %d ]\n",wcnt);
  406.     printf("[ objects:    %d ]\n",ocnt);
  407.     printf("[ actions:    %d ]\n",acnt);
  408.     printf("[ variables:  %d ]\n",vcnt);
  409.     printf("[ data:       %d ]\n",dsize);
  410.     printf("[ code:       %d ]\n",cptr);
  411.     printf("[ dictionary: %d ]\n",dptr-dsize);
  412.     printf("[ text:       %ld ]\n",(long) msgoff * 4L);
  413.     printf("[ save area:  %d ]\n",ssize);
  414.     printf("[ errors:     %d ]\n",errcount);
  415. #ifdef MAC
  416.     macpause();
  417. #endif
  418. }
  419.  
  420. /* woutput - output the word data */
  421. woutput(node)
  422.   TNODE *node;
  423. {
  424.     int wnum,wrd;
  425.  
  426.     if (node) {
  427.     woutput(LLINK(node));
  428.     wnum = WORD(node);
  429.     wrd = WORD(node) = dalloc(strlen(KEY(node))+3);
  430.     putword(wrd,wnum);
  431.     strcpy(data+wrd+2,KEY(node));
  432.     if (wtable[wnum] == WT_UNKNOWN)
  433.         printf("Type of word %s is unknown\n",KEY(node));
  434.     woutput(RLINK(node));
  435.     }
  436. }
  437.  
  438. /* wtoutput - output the word table */
  439. wtoutput(node)
  440.   TNODE *node;
  441. {
  442.     if (node) {
  443.     wtoutput(LLINK(node));
  444.     word_out(WORD(node));
  445.     wtoutput(RLINK(node));
  446.     }
  447. }
  448.  
  449. /* undef_object - complain about an undefined object */
  450. undef_object(n)
  451.   int n;
  452. {
  453.     char msg[100];
  454.     SYMBOL *sym;
  455.  
  456.     for (sym = symbols; sym != NULL; sym = sym->s_next)
  457.     if (sym->s_type == ST_OBJECT && n == sym->s_value) {
  458.         sprintf(msg,"Object %s is undefined",sym->s_name);
  459.         xerror(msg);
  460.         break;
  461.     }
  462. }
  463.  
  464. /* str_out - output a string */
  465. str_out(str,len)
  466.   char *str; int len;
  467. {
  468.     while (len--)
  469.     byte_out(*str++);
  470. }
  471.  
  472. /* word_out - output a word */
  473. word_out(dat)
  474.   int dat;
  475. {
  476.     byte_out(dat);
  477.     byte_out(dat >> 8);
  478. }
  479.  
  480. /* byte_out - output a byte */
  481. byte_out(dat)
  482.   int dat;
  483. {
  484.     ad_putc((~dat - 30) & 0xFF);
  485. }
  486.  
  487. /* oenter - enter an object into the symbol table */
  488. int oenter(name)
  489.   char *name;
  490. {
  491.     SYMBOL *sym;
  492.  
  493.     if (sym = sfind(name)) {
  494.     if (sym->s_type != ST_OBJECT)
  495.         error("Not an object");
  496.     return (sym->s_value);
  497.     }
  498.     if (ocnt < OMAX) {
  499.         senter(name,ST_OBJECT,++ocnt);
  500.         otable[ocnt] = NIL;
  501.     }
  502.     else
  503.     error("too many objects");
  504.     return (ocnt);
  505. }
  506.  
  507. /* ofind - find an object in the symbol table */
  508. int ofind(name)
  509.   char *name;
  510. {
  511.     SYMBOL *sym;
  512.  
  513.     if (sym = sfind(name)) {
  514.     if (sym->s_type != ST_OBJECT)
  515.         return (NIL);
  516.     return (sym->s_value);
  517.     }
  518.     return (NIL);
  519. }
  520.  
  521. /* aenter - enter an action into the symbol table */
  522. int aenter(name)
  523.   char *name;
  524. {
  525.     SYMBOL *sym;
  526.  
  527.     if (sym = sfind(name)) {
  528.     if (sym->s_type != ST_ACTION)
  529.         error("Not an action");
  530.     return (sym->s_value);
  531.     }
  532.     if (acnt < AMAX) {
  533.         senter(name,ST_ACTION,++acnt);
  534.         atable[acnt] = NIL;
  535.     }
  536.     else
  537.     error("too many actions");
  538.     return (acnt);
  539. }
  540.  
  541. /* venter - enter a variable into the symbol table */
  542. int venter(name)
  543.   char *name;
  544. {
  545.     SYMBOL *sym;
  546.  
  547.     if (sym = sfind(name)) {
  548.     if (sym->s_type != ST_VARIABLE)
  549.         error("Not a variable");
  550.     return (sym->s_value);
  551.     }
  552.     senter(name,ST_VARIABLE,++vcnt);
  553.     return (vcnt);
  554. }
  555.  
  556. /* penter - enter a property into the symbol table */
  557. int penter(name)
  558.   char *name;
  559. {
  560.     SYMBOL *sym;
  561.  
  562.     if (sym = sfind(name)) {
  563.     if (sym->s_type != ST_PROPERTY)
  564.         error("Not a property");
  565.     return (sym->s_value);
  566.     }
  567.     senter(name,ST_PROPERTY,++pcnt);
  568.     return (pcnt);
  569. }
  570.  
  571. /* center - enter a constant into the symbol table */
  572. center(name,value)
  573.   char *name; int value;
  574. {
  575.     if (sfind(name)) {
  576.     error("Already defined");
  577.     return;
  578.     }
  579.     senter(name,ST_CONSTANT,value);
  580. }
  581.  
  582. /* sfind - find a symbol in the symbol table */
  583. SYMBOL *sfind(name)
  584.   char *name;
  585. {
  586.     SYMBOL *sym;
  587.  
  588.     for (sym = symbols; sym != NULL; sym = sym->s_next)
  589.     if (strcmp(name,sym->s_name) == 0)
  590.         break;
  591.     return (sym);
  592. }
  593.  
  594. /* senter - enter a symbol into the symbol table */
  595. SYMBOL *senter(name,type,value)
  596.   char *name; int type,value;
  597. {
  598.     SYMBOL *sym;
  599.  
  600.     if ((sym = (SYMBOL *)malloc(sizeof(SYMBOL))) == NULL)
  601.     fail("out of memory");
  602.     sym->s_name = save(name);
  603.     sym->s_type = type;
  604.     sym->s_value = value;
  605.     sym->s_next = symbols;
  606.     symbols = sym;
  607.     return (sym);
  608. }
  609.  
  610. /* frequire - fetch a token and check it */
  611. frequire(rtkn)
  612.   int rtkn;
  613. {
  614.     require(token(),rtkn);
  615. }
  616.  
  617. /* require - check for a required token */
  618. require(tkn,rtkn)
  619.   int tkn,rtkn;
  620. {
  621.     char msg[100];
  622.     if (tkn != rtkn) {
  623.     sprintf(msg,"Expecting %s",t_names[rtkn]);
  624.     error(msg);
  625.     }
  626. }
  627.  
  628. /* save - allocate memory for a string */
  629. char *save(str)
  630.   char *str;
  631. {
  632.     char *new;
  633.  
  634.     if ((new = malloc(strlen(str)+1)) == NULL)
  635.     fail("out of memory");
  636.     strcpy(new,str);
  637.     return (new);
  638. }
  639.  
  640. /* match - compare a string with the current token */
  641. int match(str)
  642.   char *str;
  643. {
  644.     return (strcmp(str,t_token) == 0);
  645. }
  646.  
  647. /* fail - print an error message and exit */
  648. fail(msg)
  649.   char *msg;
  650. {
  651.     printf("%s\n",msg);
  652. #ifdef MAC
  653.     macpause();
  654. #endif
  655.     exit();
  656. }
  657.